<?php

namespace Jinxing\Admin\Http\Middleware;

use Closure;
use Jinxing\Admin\Helpers\Storage;
use Jinxing\Admin\Traits\ExceptTrait;
use Jinxing\Admin\Repositories\MenuRepository;
use Illuminate\Support\Facades\Auth as BaseAuth;

class Auth
{
    use ExceptTrait;

    protected $except = [];

    public function __construct()
    {
        $prefix       = config('admin.route.prefix');
        $this->except = $this->except ?: array_merge([
            $prefix . '/admins/show',
            $prefix . '/admins/update-password',
            $prefix . '/admins/upload-avatar',
            config('admin.home_url'),
        ], config('admin.except_auth', []));
    }

    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param Closure                  $next
     *
     * @return mixed
     * @throws \Exception
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function handle($request, Closure $next)
    {
        // 不需要登录的接口
        if ($this->inExceptArray($request, array_merge([
            config('admin.route.prefix') . '/login/*',
        ], config('admin.except_login', [])))) {
            return $next($request);
        }

        // 验证是否已经登录
        if (BaseAuth::guard('admin')->guest()) {
            return $this->handleUnauthorized($request);
        }

        // 需要排除指定的路由
        if ($this->inExceptArray($request, $this->except)) {
            return $next($request);
        }

        BaseAuth::shouldUse('admin');
        $uid = BaseAuth::user()->getAuthIdentifier();

        // 验证权限
        if (config('admin.verify_permissions') == true) {
            if (BaseAuth::user()->can(trim(request()->getPathInfo(), '/')) || $uid === config('admin.super_admin_id')) {
                return $next($request);
            }
        }

        // 获取菜单信息
        if (!$uris = Storage::get('uris')) {
            $uris = get_menu_uris();
            Storage::set('uris', $uris);
        }

        // 查询到用户所有菜单信息
        $menus = cache()->store('file')->get('admin:menus:' . $uid);
        if (empty($menus)) {
            // 验证是否有改菜单
            $menus = MenuRepository::instance()->findUserMenus($uid);
            $menus = array_pluck($menus, null, 'url');
            cache()->store('file')->put('admin:menus:' . $uid, $menus, 10);
        }

        foreach ($uris as $uri) {
            if (isset($menus[$uri])) {
                return $next($request);
            }
        }

        return $this->handleUnauthorized($request);
    }

    /**
     * 没有权限处理
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    protected function handleUnauthorized($request)
    {
        if ($request->ajax() || $request->wantsJson()) {
            return response('Unauthorized.', 401);
        }

        return redirect()->guest(config('admin.login_url'));
    }
}
